using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
using Impact.Infrastructure.State;
using Impact.Infrastructure.Exceptions;
using StructureMap;

namespace Impact.Infrastructure.Logging
{
    /// <summary>
    /// Logger for Impact
    /// </summary>
    [Pluggable("EntLibLogger")]
    public class EntLibLogger : ILogger
    {

        /// <summary>
        /// Writes the given message to the logging listeners
        /// </summary>
        public void Write(string message)
        {
            Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(message, "General", 1, -1, TraceEventType.Information, message, GetDefaultProperties());
        }

        /// <summary>
        /// Writes the given message to the logging listeners
        /// </summary>
        public void Write(string message, TraceEventType severity)
        {
            Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(message, "General", 1, -1, severity, message, GetDefaultProperties());
        }

        /// <summary>
        /// Writes the given exception to the logging listeners
        /// </summary>
        public void Write(Exception ex)
        {
            Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(ex, "General", 1, -1, TraceEventType.Error, ex.Message, GetDefaultProperties());
        }


        private IDictionary<string, object> GetDefaultProperties()
        {
            Dictionary<string, object> output = new Dictionary<string, object>();
            output.Add("Calling Method", GetCallingMethod());

            if (Transaction.Current != null)
            {
                output.Add("Transaction ID", Transaction.Current.TransactionId);
                output.Add("Session ID", Transaction.Current.SessionId);
                output.Add("User ID", Transaction.Current.UserId);
            }

            return output;
        }

        private string GetCallingMethod()
        {
            string methodName = string.Empty;
            StackTrace trace = new StackTrace(true);
            foreach (StackFrame frame in trace.GetFrames())
            {
                // find the first method that isn't from this class
                if (!frame.GetMethod().ReflectedType.Equals(typeof(EntLibLogger)) &&
                    !frame.GetMethod().ReflectedType.Equals(typeof(ExceptionManager)))
                {
                    methodName = string.Format("{0} {1}:{2}",
                        frame.GetMethod().DeclaringType.ToString(),
                        frame.GetMethod().ToString(),
                        frame.GetFileLineNumber());
                    break;
                }
            }
            return methodName;
        }



    }
}
